unit IOCompletionPort;

interface

uses
  Winapi.Windows, System.Classes, System.SysUtils, IException;

type
  PPOverlapped = ^POverlapped;
  TIOCompletionPort = class
  private
    FCompletionPort: Thandle;
  public
    constructor Create;
    destructor Destroy; override;
    procedure CreateCompletionPort(NumberOfConcurrentThreads: Cardinal = 0);
    function AssociateSocketWithCompletionPort(var hDevice: THandle;
      dwCompletionKey: ULONG_PTR): Boolean;
    function GetIOCompletionStatus(dwNumberOfBytesTransferred: Cardinal;
      lpCompletionKey: ULONG_PTR; lpOverlapped: POverlapped): Boolean;
    function GetQueuedCompletionStatus(var dwNumberOfBytesTransferred: Cardinal;
      var dCompletionKey: ULONG_PTR; var lpOverlapped: POverlapped): Boolean;
    function PostIOCompletionStatus(dwNumberOfBytesTransferred: Cardinal;
      dCompletionKey: ULONG_PTR; lpOverlapped: POverlapped): Boolean;
  end;

implementation

{ TIOCompletionPort }

constructor TIOCompletionPort.Create;
begin
  inherited Create;
  CreateCompletionPort;
end;

destructor TIOCompletionPort.Destroy;
begin
  CloseHandle(FCompletionPort);
  FCompletionPort := INVALID_HANDLE_VALUE;
  inherited Destroy;
end;

procedure TIOCompletionPort.CreateCompletionPort(
  NumberOfConcurrentThreads: Cardinal);
begin
  FCompletionPort := Winapi.Windows.CreateIOCompletionPort(INVALID_HANDLE_VALUE,
    0, 0, NumberOfConcurrentThreads);
  if FCompletionPort = 0 then
    raise TException.Create(GetLastError(), 'CreateIOCompletionPort');
end;

function TIOCompletionPort.AssociateSocketWithCompletionPort(
  var hDevice: THandle; dwCompletionKey: ULONG_PTR): Boolean;
begin
  Result := Winapi.Windows.CreateIoCompletionPort(hDevice, FCompletionPort,
    dwCompletionKey, 0) <> 0;
end;

function TIOCompletionPort.GetIOCompletionStatus(dwNumberOfBytesTransferred: Cardinal;
  lpCompletionKey: ULONG_PTR; lpOverlapped: POverlapped): Boolean;
begin
  Result := Winapi.Windows.GetQueuedCompletionStatus(FCompletionPort,
    dwNumberOfBytesTransferred, lpCompletionKey, lpOverlapped, INFINITE);
end;

function TIOCompletionPort.PostIOCompletionStatus(dwNumberOfBytesTransferred: Cardinal;
  dCompletionKey: ULONG_PTR; lpOverlapped: POverlapped): Boolean;
begin
  Result := Winapi.Windows.PostQueuedCompletionStatus(FCompletionPort,
    dwNumberOfBytesTransferred, dCompletionKey, lpOverlapped);
end;

function TIOCompletionPort.GetQueuedCompletionStatus(var dwNumberOfBytesTransferred: Cardinal;
  var dCompletionKey: ULONG_PTR; var lpOverlapped: POverlapped): Boolean;
begin
  Result := Winapi.Windows.GetQueuedCompletionStatus(FCompletionPort,
    dwNumberOfBytesTransferred, dCompletionKey, lpOverlapped, INFINITE);
end;

end.
